const webpack = require('webpack');
const DllPlugin = require('webpack/lib/DllPlugin');
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');
const path = require('path');

const entry = [
  ['react', ['react', 'react-dom']],
  ['react_ext', ['redux', 'react-redux', 'react-router', 'react-router-dom'], 'react'],
  ['antd', ['antd'], 'react'],
  ['echarts', ['echarts']],
];
const output = {
  filename: '[name].dll.js',
  // 输出的文件都放到 dist 目录下
  path: path.resolve(__dirname, '../public/lib'),
  // 存放动态链接库的全局变量名称，例如对应 react 来说就是 _dll_react
  // 之所以在前面加上 _dll_ 是为了防止全局变量冲突
  library: '_dll_[name]',
  libraryTarget: 'window',
};
const plugins = [
  new DllPlugin({
    // 动态链接库的全局变量名称，需要和 output.library 中保持一致
    // 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
    // 例如 react.manifest.json 中就有 "name": "_dll_react"
    name: '_dll_[name]',
    // 描述动态链接库的 manifest.json 文件输出时的文件名称
    path: path.join(__dirname, '../public/lib', '[name].manifest.json'),
  }),
];

function run(config) {
  const [name] = Object.keys(config.entry);
  console.log('开始构建：' + name);
  return new Promise((resolve) => {
    webpack(config, (err, stats) => {
      if (err) throw err;
      console.log('构建成功');
      process.nextTick(resolve);
    });
  });
}

function makeReact() {
  const [name, libs] = entry[0];
  return run({
    entry: {
      [name]: libs,
    },
    output,
    plugins,
  });
}

makeReact().then(() => {
  const [f, ...rest] = entry;
  rest.reduce((a, b) => {
    const [name, libs, dep] = b;
    const config = {
      entry: {
        [name]: libs,
      },
      output,
      plugins: [
        ...plugins,
        dep
          ? new DllReferencePlugin({
              manifest: require(`../public/lib/${dep}.manifest.json`),
            })
          : false,
      ].filter(Boolean),
    };
    return a.then(() => {
      return run(config);
    });
  }, Promise.resolve());
});
